/*!
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 *    Author: flareguner
 *    E-Mail: flareguner@gmail.com
 *    Years: 2010-2011
 */



#include "mainwindow.h"
#include "translationtabwidget.h"
#include "translationwidget.h"
#include "tools/trayicon.h"
#include "settings.h"
#include "exceptions.h"
#include "history.h"
#include "dictionarywidget.h"
#include "popup.h"
#include "pronounce.h"
#include "translate.h"
#include "defines.h"
#include "appearanceconfig.h"
#include "exceptionsconfig.h"
#include "languagesconfig.h"
#include "shortcutconfig.h"
#include "translationconfig.h"
#include "notificationsconfig.h"
#include "3rdparty/qxtshortcut/qxtglobalshortcut.h"
#include <QtGui/QAction>
#include <QtGui/QToolBar>
#include <QtGui/QMenuBar>
#include <QtGui/QMenu>
#include <QtGui/QFileDialog>
#include <QtGui/QTextDocumentFragment>
#include <QtGui/QPrinter>
#include <QtGui/QPrintDialog>
#include <QtGui/QTextDocument>
#include <QtGui/QMessageBox>
#include <QtGui/QStatusBar>
#include <QtGui/QIcon>
#include <QtCore/QSettings>
#include <QtCore/QEvent>

#include <QtCore/QTranslator>
#include <QtCore/QFile>
#include <QtNetwork/QNetworkAccessManager>
#include <QDebug>
#include <QApplication>
#include "src/platform.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    m_translate(new Translate(this))

{
    createActions();
    createToolbar();
    createMenu();
    createTools();
    createWidgets();
    createUi();
    createConnections();
    initApplication();

    updateSettings();


    if(m_settings->appearance()->getStartMinimized()) {
        this->hide();
    }

    QEvent event(QEvent::LanguageChange);
    changeEvent(&event);

//    mainToolbar->setOrientation(Qt::Vertical);

    m_window_settings = new QSettings(Platform::getOrganizationName(), Platform::getApplicationName());
    m_window_settings->beginGroup("MainWindow");
}

MainWindow::~MainWindow() {
    qDebug() << Q_FUNC_INFO;
    delete m_tab_widget;

}

//Actions slots

void MainWindow::open() {
    QFile file(QFileDialog::getOpenFileName(this, "Text (*.html *.txt)"));


    if(!file.open(QFile::ReadOnly | QFile::Text))
            return;


    // Spike for html detect (by extension :D)
    const QString ext = file.fileName().split('.').last();
    QString result;
    if(ext == "html" || ext == "htm")
        result = QTextDocumentFragment::fromHtml(file.readAll()).toPlainText();
    else
        result = file.readAll();

    m_tab_widget->instance()->setSourceLanguage(m_translate->getLanguageIndex(result));
    m_tab_widget->instance()->setSourceText(result);





}

void MainWindow::save() {

}

void MainWindow::saveAs() {

}

void MainWindow::print() {
    QPrinter printer;
       QPrintDialog print_dialog(&printer);
       if(print_dialog.exec() == QPrintDialog::Accepted) {
           QTextDocument doc(m_tab_widget->instance()->getResultText(), this);
           doc.print(&printer);
       }
}

void MainWindow::translate() {
    m_popup->setCursorPositionLocked(true);

    if(this->isHidden() || !isActiveWindow()) {
        const QString _text = m_cliboard->text(QClipboard::Selection);
        if(!_text.isEmpty())
            m_tab_widget->instance()->setSourceText(_text);
    }

    const QString text = m_tab_widget->instance()->getSourceText();

    const QString l_src = m_tab_widget->instance()->getSourceLanguage();
    const QString d_src = m_tab_widget->instance()->getResultLanguage();

    const QString res = m_translate->translate(  l_src,d_src, text);


//    m_tab_widget->setLanguagesList(m_settings->languages()->getEnabledLanguagesCodes());
    m_tab_widget->instance()->setResultText(res);


    if(m_settings->notifications()->getPopupEnabled()
            && (this->isHidden() || !isActiveWindow())) {
        m_popup->popup(res);
    }

qDebug() << 11111 << text << res << l_src << d_src;
    m_popup->setCursorPositionLocked(false);
}

void MainWindow::exit() {
    qApp->exit();
}

void MainWindow::pronounce() {
//    const QString text = m_tab_widget->instance()->getResultText();
//    const QString lang = m_tab_widget->instance()->getResultLanguage();

//    m_pronounce->say(text, lang);

//    qDebug() << Q_FUNC_INFO << lang << text;
}

void MainWindow::about() {
    QMessageBox::information(this, Platform::getApplicationName() + " - About",
                             "This is Qgoogletranslator :)");
}

void MainWindow::aboutQt() {
    QMessageBox::aboutQt(this);
}


//-----------------------------------------------------------------

void MainWindow::setLocked(bool b) {
//    this->setDisabled(b);
    mainToolbar->setDisabled(b);
    m_tab_widget->setDisabled(b);
    fileMenu->setDisabled(b);
    editMenu->setDisabled(b);
    pronounceAction->setDisabled(b);
    scanSelectionAction->setDisabled(b);
    historyAction->setDisabled(b);
    exceptionsAction->setDisabled(b);
    autoDetectAction->setDisabled(b);
    autoTranslateAction->setDisabled(b);
}

void MainWindow::lock() {
    setLocked(true);
}

void MainWindow::unlock() {
    setLocked(false);
}

//void MainWindow::clear() {

//}

//void MainWindow


void MainWindow::changeEvent(QEvent *e) {
    if(e->type() == QEvent::LanguageChange) {
        fileMenu->setTitle(QMenu::tr("File"));
        editMenu->setTitle(QMenu::tr("Edit"));
        toolsMenu->setTitle(QMenu::tr("Tools"));
        dockersMenu->setTitle(QMenu::tr("Docks"));
        helpMenu->setTitle(QMenu::tr("Help"));


        openAction->setText(QAction::tr("Open"));
        saveAction->setText(QAction::tr("Save"));
        saveAsAction->setText(QAction::tr("Save As..."));
        printAction->setText(QAction::tr("Print"));
        translateAction->setText(QAction::tr("Translate"));
        exitAction->setText(QAction::tr("Exit"));

        clearAction->setText(QAction::tr("Clear"));
        copyAction->setText(QAction::tr("Copy"));
        undoAction->setText(QAction::tr("Undo"));
        redoAction->setText(QAction::tr("Redo"));

        swapAction->setText(QAction::tr("Swap"));

        settingsAction->setText(QAction::tr("Settings"));
//        dock

        pronounceAction->setText(QAction::tr("Pronounce"));
        historyAction->setText(QAction::tr("History"));
        exceptionsAction->setText(QAction::tr("Exceptions"));
        autoDetectAction->setText(QAction::tr("Auto Detect"));
        autoTranslateAction->setText(QAction::tr("Auto Translate"));
        scanSelectionAction->setText(QAction::tr("Scan Selection"));

        dictionaryAction->setText(QAction::tr("Dictionary"));

        aboutAction->setText(QAction::tr("About"));
        aboutQtAction->setText(QAction::tr("About Qt"));



        m_dict_widget->setWindowTitle(QDockWidget::tr("Dictionary"));


//        mainToolbar->set



    }
}

void MainWindow::createActions() {
    openAction = new QAction(this);
    saveAction = new QAction(this);
    saveAsAction = new QAction(this);
    printAction = new QAction(this);
    translateAction = new QAction(this);
    exitAction = new QAction(this);

    clearAction = new QAction(this);
    copyAction = new QAction(this);
    undoAction = new QAction(this);
    redoAction = new QAction(this);
    swapAction = new QAction(this);

    settingsAction = new QAction(this);
    docksAction = new QAction(this);
    pronounceAction = new QAction(this);
    historyAction = new QAction(this);
    exceptionsAction = new QAction(this);

    autoDetectAction = new QAction(this);
    autoTranslateAction = new QAction(this);
    scanSelectionAction = new QAction(this);


    autoDetectAction->setCheckable(true);
    autoTranslateAction->setCheckable(true);
    scanSelectionAction->setCheckable(true);

    dictionaryAction = new QAction(this);
    dictionaryAction->setCheckable(true);

    aboutAction = new QAction(this);
    aboutQtAction = new QAction(this);

#ifdef QGT_OS_UNIXLIKE
    openAction->setIcon(QIcon::fromTheme("document-open"));
    saveAction->setIcon(QIcon::fromTheme("document-save"));
    saveAsAction->setIcon(QIcon::fromTheme("document-save-as"));
    printAction->setIcon(QIcon::fromTheme("document-print"));
    translateAction->setIcon(QIcon::fromTheme("go-next"));
    exitAction->setIcon(QIcon::fromTheme("application-exit"));

    clearAction->setIcon(QIcon::fromTheme("edit-clear"));
    copyAction->setIcon(QIcon::fromTheme("edit-copy"));
    undoAction->setIcon(QIcon::fromTheme("edit-undo"));
    redoAction->setIcon(QIcon::fromTheme("edit-redo"));
    swapAction->setIcon(QIcon::fromTheme("system-switch-user"));

    translateAction->setDisabled(true);

    copyAction->setDisabled(true);
    clearAction->setDisabled(true);
    undoAction->setDisabled(true);
    redoAction->setDisabled(true);


    settingsAction->setIcon(QIcon::fromTheme("preferences-desktop"));
    docksAction->setIcon(QIcon::fromTheme("preferences-desktop"));

    pronounceAction->setIcon(QIcon::fromTheme("media-playback-start"));
    historyAction->setIcon(QIcon::fromTheme("view-history")); // Check it in STD!
    exceptionsAction->setIcon(QIcon::fromTheme("edit-find-replace"));

    //NOT STD!  Fix me somebody!
    scanSelectionAction->setIcon(QIcon::fromTheme("select-rectangular"));
    autoTranslateAction->setIcon(QIcon::fromTheme("quickopen"));
    autoDetectAction->setIcon(QIcon::fromTheme("color-picker"));


    dictionaryAction->setIcon(QIcon::fromTheme("accessories-dictionary"));
    aboutAction->setIcon(QIcon::fromTheme("help-about"));
#endif

    saveAction->setDisabled(true);
    saveAsAction->setDisabled(true);
    translateAction->setDisabled(true);

    clearAction->setDisabled(true);
    copyAction->setDisabled(true);
    undoAction->setDisabled(true);
    redoAction->setDisabled(true);
    swapAction->setDisabled(true);

    pronounceAction->setDisabled(true);





}

void MainWindow::createToolbar() {

    mainToolbar = new QToolBar(this);

    mainToolbar->addAction(clearAction);
    mainToolbar->addAction(saveAction);
    mainToolbar->addAction(copyAction);
    mainToolbar->addSeparator();
    mainToolbar->addAction(undoAction);
    mainToolbar->addAction(redoAction);
    mainToolbar->addAction(pronounceAction);
    mainToolbar->addAction(historyAction);
    mainToolbar->addAction(exceptionsAction);
    mainToolbar->addSeparator();
    mainToolbar->addAction(autoTranslateAction);
    mainToolbar->addAction(autoDetectAction);
    mainToolbar->addAction(scanSelectionAction);
    mainToolbar->addSeparator();
    mainToolbar->addAction(translateAction);

    this->addToolBar(mainToolbar);
}

void MainWindow::createMenu() {
    fileMenu = new QMenu(this);
    editMenu = new QMenu(this);
    toolsMenu = new QMenu(this);
    dockersMenu = new QMenu(this);
    helpMenu = new QMenu(this);

    mainMenubar = new QMenuBar(this);

    fileMenu->addAction(openAction);
    fileMenu->addSeparator();
    fileMenu->addAction(saveAction);
    fileMenu->addAction(saveAsAction);
    fileMenu->addAction(printAction);
    fileMenu->addSeparator();
    fileMenu->addAction(translateAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    editMenu->addAction(clearAction);
    editMenu->addAction(copyAction);
    editMenu->addSeparator();
    editMenu->addAction(undoAction);
    editMenu->addAction(redoAction);
    editMenu->addSeparator();
    editMenu->addAction(swapAction);

    toolsMenu->addAction(settingsAction);
    toolsMenu->addSeparator();
    toolsMenu->addAction(pronounceAction);
    toolsMenu->addAction(historyAction);
    toolsMenu->addAction(exceptionsAction);
    toolsMenu->addSeparator();
    toolsMenu->addAction(autoDetectAction);
    toolsMenu->addAction(autoTranslateAction);
    toolsMenu->addAction(scanSelectionAction);
    toolsMenu->addSeparator();
    toolsMenu->addMenu(dockersMenu);

    dockersMenu->addAction(dictionaryAction);

    helpMenu->addAction(aboutAction);
    helpMenu->addAction(aboutQtAction);

    mainMenubar->addMenu(fileMenu);
    mainMenubar->addMenu(editMenu);
    mainMenubar->addMenu(toolsMenu);
    mainMenubar->addMenu(helpMenu);

    this->setMenuBar(mainMenubar);
}

void MainWindow::createTools() {
    m_tray_icon = new TrayIcon(this); // << (probably fixed)
    m_settings = new Settings; // << PROBLEMS HERE, OFFICER
    m_exceptions = new Exceptions(this);
    m_history = new History(this);
    m_popup = new Popup(this);
    m_pronounce = new Pronounce(this);

    m_translation_shortcut = new QxtGlobalShortcut(this);

    m_cliboard= QApplication::clipboard();
}

void MainWindow::createWidgets() {
    m_tab_widget = new TranslationTabWidget(this);
    m_dict_widget = new DictionaryWidget (this);
    m_status_bar = new QStatusBar(this);

    this->setStatusBar(m_status_bar);
}

void MainWindow::createUi() {
    this->setCentralWidget(m_tab_widget);
    this->addDockWidget(Qt::LeftDockWidgetArea, m_dict_widget);


//    Qt::DockWidgetArea area = (Qt::DockWidgetArea)m_window_settings->value("dictionaryDockArea", Qt::RightDockWidgetArea).toInt();
    this->addDockWidget(Qt::RightDockWidgetArea, m_dict_widget);
}

void MainWindow::createConnections() {
    connect(openAction, SIGNAL(triggered()),this, SLOT(open()));
    connect(saveAction, SIGNAL(triggered()),this,SLOT(save()));
    connect(saveAsAction, SIGNAL(triggered()),this, SLOT(saveAs()));
    connect(printAction, SIGNAL(triggered()),this, SLOT(print()));
    connect(translateAction, SIGNAL(triggered()),this,SLOT(translate()));
    connect(exitAction, SIGNAL(triggered()),this, SLOT(exit()));

    connect(clearAction, SIGNAL(triggered()),m_tab_widget, SLOT(clear()));
    connect(copyAction, SIGNAL(triggered()),m_tab_widget, SLOT(copy()));

    connect(undoAction, SIGNAL(triggered()),m_tab_widget, SLOT(undo()));
    connect(redoAction, SIGNAL(triggered()),m_tab_widget, SLOT(redo()));
    connect(swapAction, SIGNAL(triggered()), m_tab_widget, SLOT(swap()));

    connect(settingsAction, SIGNAL(triggered()), m_settings, SLOT(show()));
    connect(pronounceAction, SIGNAL(triggered()), this, SLOT(pronounce()));
    connect(historyAction, SIGNAL(triggered()), m_history, SLOT(show()));
    connect(exceptionsAction, SIGNAL(triggered()), m_exceptions, SLOT(show()));

    connect(aboutAction, SIGNAL(triggered()),this, SLOT(about()));
    connect(aboutQtAction, SIGNAL(triggered()), this, SLOT(aboutQt()));

    //Actions fallback
    connect(m_tab_widget, SIGNAL(saveAvailable(bool)),saveAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(saveAvailable(bool)), this->saveAsAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(saveAvailable(bool)),this->printAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(undoAvailable(bool)), this->undoAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(redoAvailable(bool)), this->redoAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(copyAvailable(bool)),this->copyAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(clearAvailable(bool)),this->clearAction, SLOT(setEnabled(bool)));

//    connect(m_tab_widget, SIGNAL(clearAvailable(bool)), this->translateAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(clearAvailable(bool)),this->pronounceAction, SLOT(setEnabled(bool)));
    connect(m_tab_widget, SIGNAL(textChanged()), this, SLOT(textChangeHandler()));



    connect(dictionaryAction, SIGNAL(toggled(bool)),m_dict_widget, SLOT(setVisible(bool)));
    connect(m_dict_widget, SIGNAL(visibilityChanged(bool)), dictionaryAction, SLOT(setChecked(bool)));

    //Tray
    connect(scanSelectionAction, SIGNAL(triggered(bool)),m_tray_icon, SLOT(setScanSelectionEnabled(bool)));
    connect(m_tray_icon, SIGNAL(scanSelectionChanged(bool)), scanSelectionAction, SLOT(setChecked(bool)));
    connect(m_tray_icon, SIGNAL(translationRequested()), this, SLOT(translate()));
    connect(m_tray_icon, SIGNAL(swapRequested()), m_tab_widget, SLOT(swap()));
    connect(m_tray_icon, SIGNAL(settingsRequested()),m_settings, SLOT(show()));
    connect(m_tray_icon, SIGNAL(exitRequested()), this, SLOT(exit()));


    //Settings

    connect(scanSelectionAction, SIGNAL(triggered(bool)), m_settings->translation(), SLOT(setScanSelection(bool)));
    connect(autoDetectAction, SIGNAL(triggered(bool)), m_settings->translation(), SLOT(setAutoDetect(bool)));
    connect(autoTranslateAction, SIGNAL(triggered(bool)), m_settings->translation(), SLOT(setAutoTranslate(bool)));

    connect(m_cliboard, SIGNAL(selectionChanged()), this, SLOT(selectionChangeHandler()));

    connect(m_settings, SIGNAL(accepted()),this, SLOT(updateSettings()));

    connect(m_tab_widget, SIGNAL(directionChanged()), this, SLOT(directionChangeHandler()));

    connect(m_tab_widget, SIGNAL(dictionaryQuery(QString)), this, SLOT(dictQuery(QString)));
}

void MainWindow::initApplication() {
    this->setWindowTitle(Platform::getApplicationName() + " " + Platform::getApplicationVersion());
}



void MainWindow::updateSettings() {

    // Retranslation
    if(m_last_translator != NULL) {
        qApp->removeTranslator(m_last_translator);
    }

    m_translator = new QTranslator;
    m_translator->load(Platform::getL10nPath() + m_settings->appearance()->getLanguage());
    qApp->installTranslator(m_translator);

    m_last_translator = m_translator;


    m_tray_icon->translate();

//----------------------------------------------------------------------------

    mainToolbar->setHidden(m_settings->appearance()->getShowToolbar());
    m_tray_icon->setVisible(!m_settings->appearance()->getShowTrayIcon());

//----------------------------------------------------------------------------

    exceptionsAction->setEnabled(m_settings->exceptions()->getExceptionsEnabled());
    m_exceptions->setCaseSensetivity(m_settings->exceptions()->getExpectionsCaseSensetive());

//----------------------------------------------------------------------------

    //! TODO: Fix this code segfault
//    const QStringList enabled = m_settings->languages()->getEnabledLanguagesCodes();
//    m_tab_widget->setLanguagesList(enabled);

//    if(enabled.isEmpty()) {
//        m_status_bar->showMessage("You must select Two or more languages!");
//        this->lock();
//    } else {
//        m_status_bar->showMessage("Thank you! Interface unlocked.");

//        this->unlock();
//    }
//m_settings->languages()->getEnabledLanguagesCodes();
//----------------------------------------------------------------------------

//place proxy code here.

//----------------------------------------------------------------------------

    translateAction->setShortcut(m_settings->shortcut()->getLocalTranslateShortcut());
    swapAction->setShortcut(m_settings->shortcut()->getSwapShortcut());

//----------------------------------------------------------------------------

    autoTranslateAction->setChecked(m_settings->translation()->getAutoTranslate());
    autoDetectAction->setChecked(m_settings->translation()->getAutoDetect());
    scanSelectionAction->setChecked(m_settings->translation()->getScanSelection());

}

void MainWindow::selectionChangeHandler() {
    if(m_settings->translation()->getScanSelection() &&(
                isHidden() || !isActiveWindow()))
        translate();
}

void MainWindow::directionChangeHandler() {
  //  m_dict_widget->setSourceLanguage(m_tab_widget->instance()->getSourceLanguage());
   // m_dict_widget->setResultLanguage(m_tab_widget->instance()->getResultLanguage());
}

void MainWindow::textChangeHandler() {
    translateAction->setEnabled(!m_tab_widget->instance()->getSourceText().isEmpty());
}

void MainWindow::dictQuery(const QString &text) {
    const QString src_lang = m_tab_widget->instance()->getSourceLanguage(),
            dest_lang = m_tab_widget->instance()->getResultLanguage();


    m_dict_widget->query(text, src_lang, dest_lang);
    qDebug() << Q_FUNC_INFO;

}
